<?php
class TeamMemberField extends TextField {
	private static $allowed_actions = array(
        'check_team'
    );
	
	protected $member_id;
	
	/**
     * The url to use as the check team member
     * @var string
     */
    protected $checkTeamURL;
	
	/**
	 * @var UsernameField
	 */
	protected $usernameField = null;
	
	/**
	 * @var NameField
	 */
	protected $nameField = null;
	
	/**
	 * @var RankField
	 */
	protected $rankField = null;
	
	/**
	 * @var IDField
	 */
	protected $idField = null;
	
	/**
	 * @var boolean
	 */
	protected $includeOwnself;
	
	/**
	 * @var boolean
	 */
	protected $includeUpline;
	
	/**
	 * @var boolean
	 */
	protected $showRank;
	
	public function __construct($name, $title = null, $value = "", $includeOwnself = true, $includeUpline = true, $showRank = true){
		Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
		Requirements::javascript(FRAMEWORK_DIR . '/javascript/i18n.js');
		Requirements::add_i18n_javascript('network/javascript/lang');
        Requirements::javascript('network/javascript/TeamMemberField.min.js');
		
		$this->usernameField = TextField::create($name . '[username]', false);
		$this->nameField = TextField::create($name . '[name]', false);
		$this->rankField = TextField::create($name . '[rank]', false);
		$this->idField = HiddenField::create($name . '[id]');
		
		$this->setIncludeOwnself($includeOwnself);
		$this->setIncludeUpline($includeUpline);
		$this->setShowRank($showRank);

		parent::__construct($name, $title, $value);
	}
	
	function Field($properties = array()) {
		$this->usernameField->setAttribute('rel', 'team-username');
		$this->usernameField->setAttribute('data-url', $this->getCheckTeamURL());
		$this->usernameField->setAttribute('data-ownself', $this->getIncludeOwnself() ? 1 : 0);
		$this->usernameField->setAttribute('data-upline', $this->getIncludeUpline() ? 1 : 0);
		$this->usernameField->setAttribute('autocomplete', 'off');
		if ($this->Required()) {
			$this->usernameField->setAttribute('required', 'required');
			$this->usernameField->setAttribute('aria-required', 'true');
		}
		$this->nameField->setAttribute('rel', 'team-name');
		$this->nameField->setAttribute('readonly', 'readonly');
		$this->nameField->setAttribute('autocomplete', 'off');
		$this->nameField->setAttribute('tabindex', '-1');
		$this->rankField->setAttribute('rel', 'team-rank');
		$this->rankField->setAttribute('readonly', 'readonly');
		$this->rankField->setAttribute('autocomplete', 'off');
		$this->rankField->setAttribute('tabindex', '-1');
		$this->idField->setAttribute('rel', 'team-id');
		$this->idField->setAttribute('autocomplete', 'off');
		if($this->getShowRank()){
			return $this->usernameField->Field() . $this->nameField->Field() . $this->rankField->Field() . $this->idField->Field();
		}
        return $this->usernameField->Field() . $this->nameField->Field() . $this->idField->Field();
    }

	function Type() {
		return 'teammember text';
	}
	
	/**
	 * Set the field value.
	 * 
	 * @param mixed $value
	 * @return FormField Self reference
	 */
	public function setValue($value) {
		if(is_array($value)) {
			$this->value = $value['username'];
		} else {
			$this->value = $value;
		}
		
		$this->usernameField->setValue($this->value);
		if($member = Distributor::get_obj_by_username($this->value)){
			$this->nameField->setValue($member->getName());
			$this->rankField->setValue($member->getRankTitle());
			$this->idField->setValue($member->ID);
		}
		else{
			$this->nameField->setValue('');
			$this->rankField->setValue('');
			$this->idField->setValue('');
		}

		return $this;
	}
	
	public function setDisabled($bool) {
		parent::setDisabled($bool);
		$this->usernameField->setDisabled($bool);
		$this->nameField->setDisabled($bool);
		$this->rankField->setDisabled($bool);
		return $this;
	}

	public function setReadonly($bool) {
		parent::setReadonly($bool);
		$this->usernameField->setReadonly($bool);
		return $this;
	}
	
	public function setIncludeOwnself($bool){
		$this->includeOwnself = $bool;
		return $this;
	}
	
	public function getIncludeOwnself(){
		return $this->includeOwnself;
	}
	
	public function setIncludeUpline($bool){
		$this->includeUpline = $bool;
		return $this;
	}
	
	public function getIncludeUpline(){
		return $this->includeUpline;
	}
	
	public function setShowRank($bool){
		$this->showRank = $bool;
		return $this;
	}
	
	public function getShowRank(){
		return $this->showRank;
	}
	
	/**
	 * Method to save this form field into the given data object.
	 * By default, makes use of $this->dataValue()
	 * 
	 * @param DataObjectInterface $record DataObject to save data into
	 */
	public function saveInto(DataObjectInterface $record) {
		$var = $this->dataValue();
		$record->setCastedField($this->getName(), $var);
		$record->setCastedField('TeamMember', $var);
	}
	
	/**
	 * Makes a read only field
	 *
	 * @return ReadonlyField
	 */
	public function performReadonlyTransformation() {
		$copy = $this->castedCopy('TeamMemberField_Readonly');
		$copy->setReadonly(true);
		$copy->usernameField = $this->usernameField->performReadonlyTransformation();
		$copy->usernameField->setReadonly(true);
		$copy->nameField = $this->nameField->performReadonlyTransformation();
		$copy->nameField->setReadonly(true);
		$copy->rankField = $this->rankField->performReadonlyTransformation();
		$copy->rankField->setReadonly(true);
		$copy->idField = $this->idField->performReadonlyTransformation();
		$copy->idField->setReadonly(true);
		$copy->setIncludeOwnself($this->getIncludeOwnself());
		$copy->setIncludeUpline($this->getIncludeUpline());
		$copy->setMemberID($this->getMemberID());
		return $copy;
	}
	
	public function setMemberID($member_id){
		$this->member_id = $member_id;
		return $this;
	}
	
	public function getMemberID(){
		return $this->member_id;
	}
	
	/**
     * Set the URL used to check team member.
     * 
     * @param string $URL The URL used for check team member.
     */
    public function setCheckTeamURL($URL) {
        $this->checkTeamURL = $url;
		return $this;
    }
	
	/**
     * Get the URL used to check team member. Returns null
     * if the built-in mechanism is used.
     *  
     * @return The URL used for check team member.
     */
    public function getCheckTeamURL() {

        if (!empty($this->checkTeamURL))
            return $this->checkTeamURL;

        // Attempt to link back to itself
        return $this->Link('check_team');
    }
	
    function validate($validator) {
    	$username = $this->Value();
		$sponsor = Sponsor::get()->find('MemberID', $this->getMemberID());
		$member_id = Distributor::get_id_by_username($username);
		if($this->getIncludeOwnself()){
	    	$result = Sponsor::get()
	    	->filter('NLeft:GreaterThanOrEqual', (int)$sponsor->NLeft)
	    	->filter('NRight:LessThanOrEqual', (int)$sponsor->NRight)
			->filter('MemberID', (int)$member_id)->count();

			if(!$result){
				$placement = Placement::get()->find('MemberID', $this->getMemberID());
				$result = Placement::get()
		    	->filter('NLeft:GreaterThanOrEqual', (int)$placement->NLeft)
		    	->filter('NRight:LessThanOrEqual', (int)$placement->NRight)
				->filter('MemberID', (int)$member_id)->count();
			}
		} else {
			$result = Sponsor::get()
	    	->filter('NLeft:GreaterThan', (int)$sponsor->NLeft)
	    	->filter('NRight:LessThan', (int)$sponsor->NRight)
			->filter('MemberID', (int)$member_id)->count();

			if(!$result){
				$placement = Placement::get()->find('MemberID', $this->getMemberID());
				$result = Placement::get()
		    	->filter('NLeft:GreaterThan', (int)$placement->NLeft)
		    	->filter('NRight:LessThan', (int)$placement->NRight)
				->filter('MemberID', (int)$member_id)->count();
			}
		}
 
 		if($this->getIncludeUpline()){
 			$upline_result = Sponsor::get()
	    	->filter('NLeft:LessThan', (int)$sponsor->NLeft)
	    	->filter('NRight:GreaterThan', (int)$sponsor->NRight)
			->filter('MemberID', (int)$member_id)->count();

			if(!$upline_result){
				$placement = Placement::get()->find('MemberID', $this->getMemberID());
				$upline_result = Placement::get()
		    	->filter('NLeft:LessThan', (int)$placement->NLeft)
		    	->filter('NRight:GreaterThan', (int)$placement->NRight)
				->filter('MemberID', (int)$member_id)->count();
			}

	 		if(!$result && !$upline_result) {
	            $validator->validationError($this->name, _t('TeamMemberField.USERNAME_INVALID', "The username is invalid"));
	            return false;
	        }
 		} else {
 			if(!$result) {
 				$validator->validationError($this->name, _t('TeamMemberField.USERNAME_INVALID', "The username is invalid"));
            	return false;
			}
 		}

        return true;
    }
	
	/**
     * Handle a request for an team member checking.
     * 
     * @param HTTPRequest $request The request to handle.
     * @return Team member data result
     */
    function check_team(HTTPRequest $request) {
    	$data = array('result' => 'error', 'id' => '', 'name' => '', 'rank' => '', 'msg' => _t('TeamMemberField.USERNAME_INVALID', "The username is invalid"));

		$sponsor = Sponsor::get()->find('MemberID', $this->getMemberID());
		$member_id = Distributor::get_id_by_username($request->getVar('username'));
    	if($this->getIncludeOwnself()){
	    	$result = Sponsor::get()
	    	->filter('NLeft:GreaterThanOrEqual', (int)$sponsor->NLeft)
	    	->filter('NRight:LessThanOrEqual', (int)$sponsor->NRight)
			->filter('MemberID', (int)$member_id)->count();
			
			if(!$result){
				$placement = Placement::get()->find('MemberID', $this->getMemberID());
				$result = Placement::get()
		    	->filter('NLeft:GreaterThanOrEqual', (int)$placement->NLeft)
		    	->filter('NRight:LessThanOrEqual', (int)$placement->NRight)
				->filter('MemberID', (int)$member_id)->count();
			}
		} else {
			$result = Sponsor::get()
	    	->filter('NLeft:GreaterThan', (int)$sponsor->NLeft)
	    	->filter('NRight:LessThan', (int)$sponsor->NRight)
			->filter('MemberID', (int)$member_id)->count();
			
			if(!$result){
				$placement = Placement::get()->find('MemberID', $this->getMemberID());
				$result = Placement::get()
		    	->filter('NLeft:GreaterThan', (int)$placement->NLeft)
		    	->filter('NRight:LessThan', (int)$placement->NRight)
				->filter('MemberID', (int)$member_id)->count();
			}
		}
		
		if($this->getIncludeUpline()){
			$upline_result = Sponsor::get()
	    	->filter('NLeft:LessThan', (int)$sponsor->NLeft)
	    	->filter('NRight:GreaterThan', (int)$sponsor->NRight)
			->filter('MemberID', (int)$member_id)->count();
			
			if(!$upline_result){
				$placement = Placement::get()->find('MemberID', $this->getMemberID());
				$upline_result = Placement::get()
		    	->filter('NLeft:LessThan', (int)$placement->NLeft)
		    	->filter('NRight:GreaterThan', (int)$placement->NRight)
				->filter('MemberID', (int)$member_id)->count();
			}
			
	 		if($result || $upline_result) {
	 			$member = Distributor::get_obj_by_username($request->getVar('username'));
	            $data = array('result' => 'success', 'id' => $member->ID, 'name' => $member->getName(), 'rank' => $member->getRankTitle(), 'msg' => _t('TeamMemberField.USERNAME_VALID', "The username is valid"));
	        }
 		} else {
 			if($result) {
 				$member = Distributor::get_obj_by_username($request->getVar('username'));
 				$data = array('result' => 'success', 'id' => $member->ID, 'name' => $member->getName(), 'rank' => $member->getRankTitle(), 'msg' => _t('TeamMemberField.USERNAME_VALID', "The username is valid"));
			}
 		}

        // the response body
        return Convert::array2json($data);
    }
}

/**
 * Readonly version of {@link TeamMemberField}.
 * Allows team member info to be represented in a form, by showing in a user friendly format.
 * @package network
 * @subpackage teammember-field
 */
class TeamMemberField_Readonly extends TeamMemberField {
	/**
	 * Include a hidden field in the HTML for the readonly field
	 * @var boolean
	 */
	protected $includeHiddenField = false;

	/**
	 * If true, a hidden field will be included in the HTML for the readonly field.
	 * 
	 * This can be useful if you need to pass the data through on the form submission, as
	 * long as it's okay than an attacker could change the data before it's submitted.
	 *
	 * This is disabled by default as it can introduce security holes if the data is not
	 * allowed to be modified by the user.
	 * 
	 * @param boolean $includeHiddenField
	 */
	public function setIncludeHiddenField($includeHiddenField) {
		$this->includeHiddenField = $includeHiddenField;
	}
	
	public function Field($properties = array()) {
		$value = $this->dataValue();
		$text = sprintf('%s - %s (%s)', $value, $this->nameField->dataValue(), $this->rankField->dataValue());
		$copy = $this->castedCopy('ReadonlyField')->setReadonly(true)->setTitle($this->title)->setValue($text);
		// Include a hidden field in the HTML
		if($this->includeHiddenField && $this->readonly) {
			return $copy->Field($properties) . $this->usernameField->performReadonlyTransformation()->setReadonly(false)->Field($properties) . $this->nameField->performReadonlyTransformation()->setReadonly(false)->Field($properties) . $this->rankField->performReadonlyTransformation()->setReadonly(false)->Field($properties) . $this->idField->performReadonlyTransformation()->setReadonly(false)->Field($properties);
		} else {
			return $copy->Field($properties);
		}
	}
}
?>
